<?php

namespace App\Http\Controllers\Admin;

use App\Exports\AfterSaleOrderExport;
use App\Http\Controllers\Controller;
use App\Jobs\CancelSkuOperationStatisticsJob;
use App\Models\AfterSaleOrder;
use App\Models\AfterSaleOrderAudit;
use App\Models\AgentRevenue;
use App\Models\CommodityActivitySkuStatistics;
use App\Models\CommodityActivityStatistics;
use App\Models\Order;
use App\Services\CacheLockKeyConst;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Http\Request;
use Illuminate\Queue\SerializableClosure;
use Illuminate\Support\Carbon;
use Symfony\Component\HttpKernel\Exception\HttpException;

class AfterSaleOrderController extends Controller
{
    public function list(Request $request)
    {
        if ($request->has('export')) {
            return (new AfterSaleOrderExport($request))->download(sprintf('售后订单(%s).xls', Carbon::now()->format('YmdHisu')));
        }

        return $this->response->array(
            AfterSaleOrder::query()
                ->join('commodities', 'commodities.id', '=', 'after_sale_orders.commodity_id')
                ->join('commodity_activities', 'commodity_activities.id', '=', 'after_sale_orders.commodity_activity_id')
                ->with(['supplier', 'order', 'agent', 'afterSaleOrderSkus'])
                ->when($request->get('numbering'), function (Builder $builder, $cond) {
                    $builder->where('after_sale_orders.numbering', $cond);
                })
                ->when($request->get('order_numbering'), function (Builder $builder, $cond) {
                    $builder->where('after_sale_orders.order_numbering', $cond);
                })
                ->when($request->get('commodity_numbering'), function (Builder $builder, $cond) {
                    $builder->where('commodities.numbering', $cond);
                })
                ->when($request->get('commodity_activity_numbering'), function (Builder $builder, $cond) {
                    $builder->where('commodity_activities.numbering', $cond);
                })
                ->when($request->get('tracking_numbering'), function (Builder $builder, $cond) {
                    // 售后的退货快递单号
                    $builder->where('return_order_numbering', 'like', "%$cond%");
                })
                ->when($request->get('client_search'), function (Builder $builder, $cond) {
                    $builder
                        ->join('orders', 'after_sale_orders.order_id', '=', 'orders.id')
                        ->where(function (Builder $builder) use ($cond) {
                            $builder
                                ->where('orders.client_phone', 'like', "%$cond%")
                                ->orWhere('orders.client_name', 'like', "%$cond%");
                        });
                })
                ->when($request->get('supplier_search'), function (Builder $builder, $cond) {
                    $builder
                        ->join('suppliers', 'after_sale_orders.supplier_id', '=', 'suppliers.id')
                        ->where(function (Builder $builder) use ($cond) {
                            $builder
                                ->where('suppliers.name', 'like', "%$cond%");
                        });
                })
                ->when($request->get('agent_search'), function (Builder $builder, $cond) {
                    $builder
                        ->join('agents', 'after_sale_orders.agent_id', '=', 'agents.id')
                        ->where(function (Builder $builder) use ($cond) {
                            $builder
                                ->where('agents.phone', 'like', "%$cond%")
                                ->orWhere('agents.name', 'like', "%$cond%");
                        });
                })
                ->when($request->get('status', AfterSaleOrder::STATUS_CANCELLED), function (Builder $builder, $cond) {
                    if ($cond === AfterSaleOrder::STATUS_CANCELLED) {
                        // 不读取已取消的售后
                        $builder->whereIn('after_sale_orders.status', [
                            AfterSaleOrder::STATUS_PENDING_REVIEW,
                            AfterSaleOrder::STATUS_FOLLOWING_UP,
                            AfterSaleOrder::STATUS_PASSED,
                            AfterSaleOrder::STATUS_DID_NOT_PASS,
                        ]);
                    } else {
                        $builder->where('after_sale_orders.status', $cond);
                    }
                })
                ->when($request->get('type'), function (Builder $builder, $cond) {
                    $builder->where('after_sale_orders.type', $cond);
                })
                ->when($request->get('created_at_begin'), function (Builder $query, $createdAtBegin) {
                    $query->where('after_sale_orders.created_at', '>=', $createdAtBegin);
                })
                ->when($request->get('created_at_end'), function (Builder $query, $createdAtEnd) {
                    $query->where('after_sale_orders.created_at', '<=', Carbon::parse($createdAtEnd)->endOfDay());
                })
                ->select(['after_sale_orders.*', 'commodities.numbering as commodity_numbering', 'commodity_activities.numbering as commodity_activity_numbering'])
                ->paginate()
        );
    }

    public function info($id)
    {
        return $this->response->array(
            AfterSaleOrder::query()
                ->with([
                    'agent', 'supplier', 'attachments', 'order',
                    'audit.administrator', 'afterSaleOrderSkus',
                    'courierInformation.courierCompany', 'client' => function (BelongsTo $builder) {
                        $builder->with(['province', 'city', 'area']);
                    }])
                ->findOrFail($id)
                ->toArray()
        );
    }

    /**
     * 审核
     */
    public function audit(Request $request, $id)
    {
        try {
            $reqStatus = (int) $request->get('status');
            $afterSaleOrder = AfterSaleOrder::query()->with(['agent', 'afterSaleOrderSkus', 'order'])->findOrFail($id);
            if ($afterSaleOrder['status'] === $reqStatus) {
                throw new HttpException(400, '请勿重复提交状态');
            }
            if (in_array((int) $afterSaleOrder['status'], [
                AfterSaleOrder::STATUS_PASSED,
                AfterSaleOrder::STATUS_DID_NOT_PASS,
                AfterSaleOrder::STATUS_CANCELLED
            ], true)) {
                throw new HttpException(400, '审核已经完成,请勿再次提交');
            }
            if ($afterSaleOrder['status'] === AfterSaleOrder::STATUS_FOLLOWING_UP
                && !in_array($reqStatus, [AfterSaleOrder::STATUS_PASSED, AfterSaleOrder::STATUS_DID_NOT_PASS], true)) {
                throw new HttpException(400, '跟进中状态只能选择通过或者未通过');
            }

            \DB::beginTransaction();

            // 记录审核日志
            $auditRecord = $afterSaleOrder->audit()->create([
                'operator_id' => $this->user['id'],
                'audit_remarks' => $request->get('audit_remarks', ''),
                'status' => $reqStatus
            ]);
            $auditRecordId = $auditRecord->getKey();
            // 更新订单状态
            $afterSaleOrderOriginalStatus = $afterSaleOrder->status;
            $afterSaleOrder->update(['status' => $reqStatus]);
            $afterSaleOrderId = $afterSaleOrder->getKey();

            if ($reqStatus === AfterSaleOrder::STATUS_PASSED) {
                // 根据不同的类型处理通过后的逻辑
                switch ($afterSaleOrder['type']) {
                    // 退款 + 退运费
                    case AfterSaleOrder::TYPE_RETURN:
                        // 退运费
                        $afterSaleOrder->refund_shipping > 0 && $afterSaleOrder->agent
                            ->incrementOrDecrementBalance(
                                $afterSaleOrder->refund_shipping,
                                AgentRevenue::TYPE_EXCHANGE_FREIGHT_COMPENSATION,
                                $afterSaleOrder
                            );
                        // [统计] 退货 Sku ID 以及数量
                        $skuWithQuantity = [];
                        foreach ($afterSaleOrder->afterSaleOrderSkus as $sku) {
                            $skuWithQuantity[$sku['commodity_activity_sku_id']] = $sku['amount'];
                        }
                        if (empty($skuWithQuantity)) {
                            $this->response->errorBadRequest('售后订单 SKU 获取发生异常');
                        }
                        dispatch_now(
                            new CancelSkuOperationStatisticsJob(
                                $skuWithQuantity,
                                $afterSaleOrder['order_id'],
                                false,
                                // [统计] 商品 sku 增加退货数量
                                new SerializableClosure(function (CommodityActivitySkuStatistics $commodityActivitySkuStatistics, $unitPrice, $quantity) {
                                    $commodityActivitySkuStatistics->incrementOrDecrementTotalReturns($unitPrice, $quantity);
                                }),
                                // 完成后增加订单退货总数
                                new SerializableClosure(function (Order $order) use ($skuWithQuantity) {
                                    $order->increment('total_number_of_returned', array_sum(array_values($skuWithQuantity)));
                                }),
                                // 失败回滚
                                new SerializableClosure(function (Order $order) use ($auditRecordId, $afterSaleOrderId, $afterSaleOrderOriginalStatus) {
                                    AfterSaleOrderAudit::query()->find($auditRecordId)->delete();
                                    AfterSaleOrder::query()->find($afterSaleOrderId)->update(['status' => $afterSaleOrderOriginalStatus]);
                                })
                            ));
                        break;
                    // 重发货 地址
                    case AfterSaleOrder::TYPE_HEAVY_SHIPMENT:
                        // 添加快递信息
                        $afterSaleOrder->courierInformation()->create([
                            'courier_company_id' => $request->get('courier_company_id'),
                            'tracking_numbering' => $request->get('tracking_numbering')
                        ]);
                        break;
                    // 只退款
                    case AfterSaleOrder::TYPE_REFUND_ONLY:
                        // [统计] 退货 Sku ID 以及数量
                        $skuWithQuantity = [];
                        foreach ($afterSaleOrder->afterSaleOrderSkus as $sku) {
                            $skuWithQuantity[$sku['commodity_activity_sku_id']] = $sku['amount'];
                        }
                        if (empty($skuWithQuantity)) {
                            $this->response->errorBadRequest('售后订单 SKU 获取发生异常');
                        }
                        dispatch_now(
                            new CancelSkuOperationStatisticsJob(
                                $skuWithQuantity,
                                $afterSaleOrder['order_id'],
                                false,
                                // [统计] 商品 sku 增加退款数量
                                new SerializableClosure(function (CommodityActivitySkuStatistics $commodityActivitySkuStatistics, $unitPrice, $quantity) {
                                    $commodityActivitySkuStatistics->incrementOrDecrementTotalRefunds($unitPrice, $quantity);
                                }),
                                // 完成后增加订单退货总数
                                new SerializableClosure(function (Order $order) use ($skuWithQuantity) {
                                    $order->increment('total_number_of_refunded', array_sum(array_values($skuWithQuantity)));
                                }),
                                // 失败回滚
                                new SerializableClosure(function (Order $order) use ($auditRecordId, $afterSaleOrderId, $afterSaleOrderOriginalStatus) {
                                    AfterSaleOrderAudit::query()->find($auditRecordId)->delete();
                                    AfterSaleOrder::query()->find($afterSaleOrderId)->update(['status' => $afterSaleOrderOriginalStatus]);
                                })
                            ));
                        break;
                    // 补偿 补偿款
                    case AfterSaleOrder::TYPE_MAKE_UP:
                        $afterSaleOrder->agent->incrementOrDecrementBalance($afterSaleOrder['compensation'], AgentRevenue::TYPE_MAKE_UP, $afterSaleOrder);
                        // [统计] 商品活动补偿款
                        /** @var CommodityActivityStatistics $commodityActivityStatistics */
                        CacheLockKeyConst::commodityActivityStatistics($afterSaleOrder['commodity_id'], $afterSaleOrder['commodity_activity_id'])
                            ->incrementOrDecrementCompensation($afterSaleOrder['compensation']);
                        break;
                    default:
                        throw new HttpException(400, '不存在的售后类型');
                }
            }

            \DB::commit();
        } catch (\Exception $e) {
            \DB::rollBack();

            $this->response->errorBadRequest($e->getMessage());
        }

        activity()
            ->on($afterSaleOrder)
            ->by(\Auth::user())
            ->withProperty('ip', app('request')->ip())
            ->log(sprintf('售后订单(%s)处理 操作: %s 意见内容: %s', $afterSaleOrder['order_numbering'], AfterSaleOrderAudit::STATUS_MAP[$reqStatus] ?? '', $request->get('audit_remarks', '')));

        return $this->response->created(null);
    }
}
